VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "clsQuadNegative"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

Private Declare Function CreatePen Lib "gdi32.dll" (ByVal nPenStyle As Long, ByVal nWidth As Long, ByVal crColor As Long) As Long
Private Declare Function CreateSolidBrush Lib "gdi32.dll" (ByVal crColor As Long) As Long
Private Declare Function PolyPolyline Lib "gdi32.dll" (ByVal hdc As Long, ByRef lppt As POINTAPI, ByRef lpdwPolyPoints As Long, ByVal cCount As Long) As Long
Private Declare Function SelectObject Lib "gdi32.dll" (ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteObject Lib "gdi32.dll" (ByVal hObject As Long) As Long
Private Declare Function FillRect Lib "user32.dll" (ByVal hdc As Long, ByRef lpRect As RECT, ByVal hBrush As Long) As Long
Private Declare Function GetStockObject Lib "gdi32.dll" (ByVal nIndex As Long) As Long
Private Declare Function Ellipse Lib "gdi32.dll" (ByVal hdc As Long, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
Private Declare Function GetSysColor Lib "user32.dll" (ByVal nIndex As Long) As Long
Private Const NULL_BRUSH As Long = 5
Private Const WHITE_BRUSH As Long = 0
Private Const BLACK_BRUSH As Long = 4

Private Type POINTAPI
    x As Long
    y As Long
End Type

Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)

Implements IGameState

Private Type typeQuadState
 nPlayerJustMoved As Byte 'this also means the total quads on the board
 nResult As Byte 'always precomputed, 0=not finished, 1=draw (impossible in this mode), 2=win w.r.t playerJustMoved, 3=lose, i.e. the real one Xor 3
 nQuazarUsed(1) As Byte 'quazar used for player 1,2 (the first player has 0.5 handicap)
 b(120) As Byte '1,2=quad of player, 3=quazar, &H10,&H20=potential winning position (bitfield) (for MCTS and winning check)
End Type

Private m_t As typeQuadState
Private m_bMove(15) As Byte '1-15=bit field of quazars position, 0=quad position, bit7 in 0 is temp

Private Sub IGameState_ClearUserMoves()
Erase m_bMove
End Sub

Friend Sub CloneFrom(ByRef t As typeQuadState)
m_t = t
End Sub

Private Function IGameState_Clone() As IGameState
Dim obj As New clsQuadNegative
obj.CloneFrom m_t
Set IGameState_Clone = obj
End Function

'warning: no sanity check!
Private Function IGameState_DoMove(ByVal lpData As Long, ByVal nSize As Long) As Boolean
Dim idx As Long
Dim i As Long, j As Long, k As Long
Dim i0 As Long, j0 As Long
Dim ii As Long, jj As Long, kk As Long
Dim i2 As Long, j2 As Long, k2 As Long
Dim bMove(15) As Byte
'///
If lpData = 0 Or nSize < 16 Then Exit Function
CopyMemory bMove(0), ByVal lpData, 16
'///
IGameState_DoMove = True
'///
idx = m_t.nPlayerJustMoved And 1&
'///place quazars.
i = 0
i0 = 0
For j = 1 To 119 'exclude corners
 If j <> 10 And j <> 110 Then 'exclude corners
  i0 = i0 \ 2&
  If i0 <= 1 Then
   i = i + 1
   i0 = &H100& Or bMove(i)
  End If
  If i0 And 1& Then
   m_t.b(j) = 3
   m_t.nQuazarUsed(idx) = m_t.nQuazarUsed(idx) + 1
  End If
 End If
Next j
'///place blocks and check winning state
j = bMove(0) - 1&
idx = idx + 1
If m_t.b(j) And (idx * &H10&) Then m_t.nResult = 2
m_t.b(j) = idx
'///update moves
m_t.nPlayerJustMoved = m_t.nPlayerJustMoved + 1
'///check if the board is full
If m_t.nResult = 0 Then
 If m_t.nPlayerJustMoved + m_t.nQuazarUsed(0) + m_t.nQuazarUsed(1) >= 117& Then
  m_t.nResult = 2 - (m_t.nQuazarUsed(0) < m_t.nQuazarUsed(1))
  If m_t.nPlayerJustMoved And 1& Then m_t.nResult = 5 - m_t.nResult
 End If
End If
'///update potential position
If m_t.nResult = 0 And m_t.nPlayerJustMoved >= 5 Then
 j0 = j \ 11
 i0 = j - j0 * 11
 k = 0
 For j = -j0 To 10 - j0
  For i = -i0 To 10 - i0
   If m_t.b(k) = idx Then
    If i <> 0 Or j <> 0 Then
     ii = i0 + i - j
     jj = j0 + j + i
     i2 = i0 - j
     j2 = j0 + i
     If ii >= 0 And jj >= 0 And ii < 11 And jj < 11 Then
      If i2 >= 0 And j2 >= 0 And i2 < 11 And j2 < 11 Then
       kk = jj * 11 + ii
       k2 = j2 * 11 + i2
       If m_t.b(kk) = idx Then
        If (i2 <> 0 And i2 <> 10) Or (j2 <> 0 Or j2 <> 10) Then
         If (m_t.b(k2) And &HF&) = 0 Then
          m_t.b(k2) = m_t.b(k2) Or (idx * &H10&)
         End If
        End If
       ElseIf m_t.b(k2) = idx Then
        If (ii <> 0 And ii <> 10) Or (jj <> 0 Or jj <> 10) Then
         If (m_t.b(kk) And &HF&) = 0 Then
          m_t.b(kk) = m_t.b(kk) Or (idx * &H10&)
         End If
        End If
       End If
      End If
     End If
     ii = i0 + i + j
     jj = j0 + j - i
     i2 = i0 + j
     j2 = j0 - i
     If ii >= 0 And jj >= 0 And ii < 11 And jj < 11 Then
      If i2 >= 0 And j2 >= 0 And i2 < 11 And j2 < 11 Then
       If m_t.b(jj * 11 + ii) = idx Then
        If (i2 <> 0 And i2 <> 10) Or (j2 <> 0 Or j2 <> 10) Then
         k2 = j2 * 11 + i2
         If (m_t.b(k2) And &HF&) = 0 Then
          m_t.b(k2) = m_t.b(k2) Or (idx * &H10&)
         End If
        End If
       End If
      End If
     End If
    End If
   End If
   k = k + 1
  Next i
 Next j
 'remove invalid potential position
 m_t.b(0) = 0
 m_t.b(10) = 0
 m_t.b(110) = 0
 m_t.b(120) = 0
End If
End Function

Private Function IGameState_Draw(ByVal bm As cDIBSection, ByVal nWidth As Long, ByVal nHeight As Long) As Boolean
Dim w As Long
Dim hbr(3) As Long, hpn(2) As Long
Dim r As RECT
Dim i As Long, j As Long, k As Long
Dim ii As Long, jj As Long
Dim p(23) As POINTAPI, m2(11) As Long
'///
w = nWidth \ 11
i = nHeight \ 14
If w > i Then w = i
'///background
hbr(0) = CreateSolidBrush(GetSysColor(vbButtonFace And &HFF&))
r.Right = nWidth
r.Bottom = nHeight
FillRect bm.hdc, r, hbr(0)
DeleteObject hbr(0)
'///
hbr(0) = SelectObject(bm.hdc, GetStockObject(NULL_BRUSH))
hbr(1) = GetStockObject(BLACK_BRUSH)
hbr(2) = GetStockObject(WHITE_BRUSH)
hbr(3) = CreateSolidBrush(&H808080)
hpn(1) = CreatePen(0, 2, vbBlack)
hpn(2) = CreatePen(2, 1, vbBlack)
hpn(0) = SelectObject(bm.hdc, hpn(1))
'///
For i = 0 To 11
 m2(i) = 2
Next i
'///draw GUI
Form1.m_fnt.DrawTextXP bm.hdc, "Reset", 0, 0, w * 2, w, DT_CENTER Or DT_VCENTER Or DT_SINGLELINE Or DT_NOCLIP, vbBlack, , True
If (m_bMove(0) And &H7F&) > 0 Then
 Form1.m_fnt.DrawTextXP bm.hdc, "OK", w * 9, 0, w * 2, w, DT_CENTER Or DT_VCENTER Or DT_SINGLELINE Or DT_NOCLIP, vbBlack, , True
End If
r.Left = (m_bMove(0) >= &H80& And (w * 2)) + ((m_t.nPlayerJustMoved And 1&) <> 0 And (w * 7))
r.Top = w * 12
r.Right = r.Left + w * 2
r.Bottom = r.Top + w
FillRect bm.hdc, r, hbr(3)
p(0).x = w * 2 + 4
p(0).y = r.Top + 4
p(1).x = p(0).x + w - 8
p(1).y = r.Top + w - 4
p(2).x = p(0).x
p(2).y = p(1).y
p(3).x = p(1).x
p(3).y = p(0).y
For i = 0 To 3
 p(i + 4).x = p(i).x + w * 7
 p(i + 4).y = p(i).y
Next i
PolyPolyline bm.hdc, p(0), m2(0), 4&
SelectObject bm.hdc, hbr(1)
Ellipse bm.hdc, 4, p(0).y, w - 4, p(1).y
SelectObject bm.hdc, hbr(2)
Ellipse bm.hdc, w * 7 + 4, p(0).y, w * 8 - 4, p(1).y
Form1.m_fnt.DrawTextXP bm.hdc, ChrW(&H221E&), w, r.Top, w, w, DT_VCENTER Or DT_SINGLELINE Or DT_NOCLIP, vbBlack, , True
Form1.m_fnt.DrawTextXP bm.hdc, ChrW(&H221E&), w * 3, r.Top, w, w, DT_VCENTER Or DT_SINGLELINE Or DT_NOCLIP, vbBlack, , True
Form1.m_fnt.DrawTextXP bm.hdc, ChrW(&H221E&), w * 8, r.Top, w, w, DT_VCENTER Or DT_SINGLELINE Or DT_NOCLIP, vbBlack, , True
Form1.m_fnt.DrawTextXP bm.hdc, ChrW(&H221E&), w * 10, r.Top, w, w, DT_VCENTER Or DT_SINGLELINE Or DT_NOCLIP, vbBlack, , True
Form1.m_fnt.DrawTextXP bm.hdc, "Score: " + CStr(-m_t.nQuazarUsed(0)), 0, r.Top + w, 0, w, DT_VCENTER Or DT_SINGLELINE Or DT_NOCLIP, vbBlack, , True
Form1.m_fnt.DrawTextXP bm.hdc, "Score: " + Format(0.5! - m_t.nQuazarUsed(1), "0.0"), w * 11, r.Top + w, 0, w, DT_RIGHT Or DT_VCENTER Or DT_SINGLELINE Or DT_NOCLIP, vbBlack, , True
'///draw chessboard
For i = 0 To 11
 p(i * 2).x = w * i
 p(i * 2).y = w
 p(i * 2 + 1).x = p(i * 2).x
 p(i * 2 + 1).y = w * 12
Next i
p(0).y = w * 2
p(1).y = p(1).y - w
p(22).y = w * 2
p(23).y = p(23).y - w
PolyPolyline bm.hdc, p(0), m2(0), 12&
For i = 0 To 23
 j = p(i).x + w
 p(i).x = p(i).y - w
 p(i).y = j
Next i
PolyPolyline bm.hdc, p(0), m2(0), 12&
'///draw marbles
k = 0
For j = 0 To 10
 p(0).x = 4
 p(0).y = w * (j + 1) + 4
 p(1).x = w - 4
 p(1).y = p(0).y + w - 8
 p(2).x = p(0).x
 p(2).y = p(1).y
 p(3).x = p(1).x
 p(3).y = p(0).y
 For i = 0 To 10
  Select Case m_t.b(k)
  Case 1
   SelectObject bm.hdc, hbr(1)
   Ellipse bm.hdc, p(0).x, p(0).y, p(1).x, p(1).y
  Case 2
   SelectObject bm.hdc, hbr(2)
   Ellipse bm.hdc, p(0).x, p(0).y, p(1).x, p(1).y
  Case 3
   PolyPolyline bm.hdc, p(0), m2(0), 2&
  End Select
  '///debug
  If m_t.b(k) And &H30& Then
   If (i <> 0 And i <> 10) Or (j <> 0 And j <> 10) Then
    Form1.m_fnt.DrawTextXP bm.hdc, CStr(m_t.b(k) \ &H10&), w * i, w * (j + 1), w, w, DT_CENTER Or DT_VCENTER Or DT_SINGLELINE Or DT_NOCLIP, vbBlack, , True
   End If
  End If
  '///
  k = k + 1
  p(0).x = p(0).x + w
  p(1).x = p(1).x + w
  p(2).x = p(2).x + w
  p(3).x = p(3).x + w
 Next i
Next j
'///draw winning square
If m_t.nResult And 2& Then
 m2(0) = 5
 For j = 0 To 10
  For i = 0 To 10
   r.Left = m_t.b(j * 11 + i) And &HF&
   If r.Left = 1 Or r.Left = 2 Then
    p(0).x = i
    p(0).y = j
    For jj = 1 To 10 - j
     For ii = 0 To j
      p(1).x = i + ii
      p(1).y = j + jj
      p(2).x = i + ii + jj
      p(2).y = j - ii + jj
      p(3).x = i + jj
      p(3).y = j - ii
      If p(2).x >= 11 Then Exit For
      If (m_t.b(p(1).y * 11 + p(1).x) And &HF&) = r.Left Then
       If (m_t.b(p(2).y * 11 + p(2).x) And &HF&) = r.Left Then
        If (m_t.b(p(3).y * 11 + p(3).x) And &HF&) = r.Left Then
         For k = 0 To 3
          p(k + 4).x = w * p(k).x + w \ 2
          p(k + 4).y = w * (p(k).y + 1) + w \ 2
         Next k
         p(8).x = p(4).x
         p(8).y = p(4).y
         PolyPolyline bm.hdc, p(4), m2(0), 1&
        End If
       End If
      End If
     Next ii
    Next jj
   End If
  Next i
 Next j
 m2(0) = 2
End If
'///draw candidates
SelectObject bm.hdc, hpn(2)
SelectObject bm.hdc, hbr(3& - (m_t.nPlayerJustMoved And 1&))
'quad
j = m_bMove(0) And &H7F&
If j > 0 Then
 j = j - 1
 k = j \ 11&
 j = j - k * 11&
 p(0).x = w * j + 4
 p(0).y = w * (k + 1) + 4
 p(1).x = p(0).x + w - 8
 p(1).y = p(0).y + w - 8
 Ellipse bm.hdc, p(0).x, p(0).y, p(1).x, p(1).y
End If
'quazar
i = 0
ii = 0
For jj = 1 To 119 'exclude corners
 If jj <> 10 And jj <> 110 Then 'exclude corners
  ii = ii \ 2&
  If ii <= 1 Then
   i = i + 1
   ii = &H100& Or m_bMove(i)
  End If
  If ii And 1& Then
   k = jj \ 11&
   j = jj - k * 11&
   p(0).x = w * j + 4
   p(0).y = w * (k + 1) + 4
   p(1).x = p(0).x + w - 8
   p(1).y = p(0).y + w - 8
   p(2).x = p(0).x
   p(2).y = p(1).y
   p(3).x = p(1).x
   p(3).y = p(0).y
   PolyPolyline bm.hdc, p(0), m2(0), 2&
  End If
 End If
Next jj
'///over
SelectObject bm.hdc, hbr(0)
SelectObject bm.hdc, hpn(0)
DeleteObject hbr(3)
DeleteObject hpn(1)
DeleteObject hpn(2)
End Function

Private Function IGameState_FilterByRandomFactor(ByVal lpData As Long, ByVal nSize As Long) As Boolean
IGameState_FilterByRandomFactor = True
End Function

Private Function IGameState_GetMoves(bData() As Byte, nSize As Long, ByVal bRespectRandomFactor As Boolean) As Long
Dim i As Long, iii As Long, k As Long, l As Long
Dim idx As Long
Dim b(119) As Byte, m As Long
Dim b2(119) As Byte, m2 As Long
'///
nSize = 16
'///checking potential winning position
idx = ((m_t.nPlayerJustMoved And 1&) + 1&) * &H10&
For k = 1 To 119 'exclude corners
 l = m_t.b(k)
 If l And idx Then
  'prefer winning move
  ReDim bData(15)
  IGameState_GetMoves = 1
  bData(0) = k + 1
  Exit Function
 ElseIf l And (&H30& Xor idx) Then
  'record losing position
  b(m) = k + 1
  m = m + 1
 End If
 'record empty position
 If (l And &HF&) = 0 And k <> 10 And k <> 110 Then
  b2(m2) = k + 1
  m2 = m2 + 1
 End If
Next k
'///list all (promising) moves
'there are enough quazars
'TODO: list moves which use more quazars
If m2 <= 0 Then Exit Function
ReDim bData(m2 * 16& - 1)
IGameState_GetMoves = m2
For iii = 0 To m2 - 1
 l = b2(iii)
 bData(iii * 16&) = l
 For i = 0 To m - 1
  If b(i) <> l Then
   k = b(i) - 1
   If k > 110 Then k = k - 1
   If k > 10 Then k = k - 1
   k = k - 1
   idx = iii * 16& + 1 + k \ 8&
   Select Case k And 7&
   Case 0: bData(idx) = bData(idx) Or &H1&
   Case 1: bData(idx) = bData(idx) Or &H2&
   Case 2: bData(idx) = bData(idx) Or &H4&
   Case 3: bData(idx) = bData(idx) Or &H8&
   Case 4: bData(idx) = bData(idx) Or &H10&
   Case 5: bData(idx) = bData(idx) Or &H20&
   Case 6: bData(idx) = bData(idx) Or &H40&
   Case 7: bData(idx) = bData(idx) Or &H80&
   End Select
  End If
 Next i
Next iii
End Function

Private Function IGameState_GetRandomMoves(bData() As Byte, nSize As Long, ByVal bReversed As Boolean) As Boolean
Dim i As Long, k As Long, l As Long
Dim idx As Long
Dim b(119) As Byte, m As Long
Dim b2(119) As Byte, m2 As Long
'///
If bReversed Then Exit Function
If m_t.nPlayerJustMoved + m_t.nQuazarUsed(0) + m_t.nQuazarUsed(1) >= 117& Then Exit Function
'///
nSize = 16
ReDim bData(15)
IGameState_GetRandomMoves = True
'///checking potential winning position
idx = ((m_t.nPlayerJustMoved And 1&) + 1&) * &H10&
For k = 1 To 119 'exclude corners
 l = m_t.b(k)
 If l And idx Then
  'prefer winning move
  bData(0) = k + 1
  Exit Function
 ElseIf l And (&H30& Xor idx) Then
  'record losing position
  b(m) = k + 1
  m = m + 1
 End If
 'record empty position
 If (l And &HF&) = 0 And k <> 10 And k <> 110 Then
  b2(m2) = k + 1
  m2 = m2 + 1
 End If
Next k
'///create random move
'there are enough quazars
'TODO: randomly use more quazars
l = b2(Int(m2 * Rnd)) 'choose a random position
bData(0) = l
For i = 0 To m - 1
 If b(i) <> l Then
  k = b(i) - 1
  If k > 110 Then k = k - 1
  If k > 10 Then k = k - 1
  k = k - 1
  idx = 1 + k \ 8&
  Select Case k And 7&
  Case 0: bData(idx) = bData(idx) Or &H1&
  Case 1: bData(idx) = bData(idx) Or &H2&
  Case 2: bData(idx) = bData(idx) Or &H4&
  Case 3: bData(idx) = bData(idx) Or &H8&
  Case 4: bData(idx) = bData(idx) Or &H10&
  Case 5: bData(idx) = bData(idx) Or &H20&
  Case 6: bData(idx) = bData(idx) Or &H40&
  Case 7: bData(idx) = bData(idx) Or &H80&
  End Select
 End If
Next i
End Function

Private Function IGameState_GetResult(ByVal nPlayerJustMoved As Long) As Long
Dim i As Long
i = m_t.nResult
IGameState_GetResult = i Xor 3 Xor (i >= 2 And (nPlayerJustMoved Xor m_t.nPlayerJustMoved) And 1&)
End Function

Private Function IGameState_GetUserMoves(bData() As Byte, nSize As Long) As Boolean
If (m_bMove(0) And &H7F&) > 0 Then
 m_bMove(0) = m_bMove(0) And &H7F&
 nSize = 16
 bData = m_bMove
 IGameState_GetUserMoves = True
End If
End Function

Private Function IGameState_OnMouseDown(ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal Button As MouseButtonConstants, ByVal Shift As ShiftConstants) As Long
Dim i As Long, j As Long, k As Long, idx As Long
'///
nWidth = nWidth \ 11
nHeight = nHeight \ 14
If nWidth > nHeight Then nWidth = nHeight
'///
If x < 0 Or y < 0 Then Exit Function
x = x \ nWidth
y = y \ nWidth
If x >= 11 Or y >= 13 Then Exit Function
'///
If Button = vbRightButton Then
 Erase m_bMove
 IGameState_OnMouseDown = 1
 Exit Function
ElseIf y = 0 Then
 If x <= 1 Then
  Erase m_bMove
  IGameState_OnMouseDown = 1
  Exit Function
 ElseIf x >= 9 And (m_bMove(0) And &H7F&) > 0 Then
  IGameState_OnMouseDown = 2
  Exit Function
 End If
ElseIf y = 12 Then
 If m_t.nPlayerJustMoved And &H1& Then x = x - 7
 If x >= 0 And x < 4 Then
  If x < 2 Then
   m_bMove(0) = m_bMove(0) And &H7F&
  Else
   m_bMove(0) = m_bMove(0) Or &H80&
  End If
  IGameState_OnMouseDown = 1
  Exit Function
 End If
ElseIf (x <> 0 And x <> 10) Or (y <> 1 And y <> 11) Then
 y = y - 1
 j = y * 11 + x
 If (m_t.b(j) And &HF&) = 0 Then
  j = j + 1
  If (m_bMove(0) And &H7F&) <> j Then
   k = j - 1
   If k > 110 Then k = k - 1
   If k > 10 Then k = k - 1
   k = k - 1
   idx = 1 + k \ 8&
   If m_bMove(0) And &H80& Then
    'place quazar
    Select Case k And 7&
    Case 0: m_bMove(idx) = m_bMove(idx) Xor &H1&
    Case 1: m_bMove(idx) = m_bMove(idx) Xor &H2&
    Case 2: m_bMove(idx) = m_bMove(idx) Xor &H4&
    Case 3: m_bMove(idx) = m_bMove(idx) Xor &H8&
    Case 4: m_bMove(idx) = m_bMove(idx) Xor &H10&
    Case 5: m_bMove(idx) = m_bMove(idx) Xor &H20&
    Case 6: m_bMove(idx) = m_bMove(idx) Xor &H40&
    Case 7: m_bMove(idx) = m_bMove(idx) Xor &H80&
    End Select
    IGameState_OnMouseDown = 1
    Exit Function
   Else
    'place block
    Select Case k And 7&
    Case 0: idx = m_bMove(idx) And &H1&
    Case 1: idx = m_bMove(idx) And &H2&
    Case 2: idx = m_bMove(idx) And &H4&
    Case 3: idx = m_bMove(idx) And &H8&
    Case 4: idx = m_bMove(idx) And &H10&
    Case 5: idx = m_bMove(idx) And &H20&
    Case 6: idx = m_bMove(idx) And &H40&
    Case 7: idx = m_bMove(idx) And &H80&
    End Select
    If idx = 0 Then
     m_bMove(0) = j
     IGameState_OnMouseDown = 1
     Exit Function
    End If
   End If
  End If
 End If
End If
'///
Beep
End Function

Private Function IGameState_OnMouseMove(ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal Button As MouseButtonConstants, ByVal Shift As ShiftConstants) As Long
'do nothing
End Function

Private Function IGameState_OnMouseUp(ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal Button As MouseButtonConstants, ByVal Shift As ShiftConstants) As Long
'do nothing
End Function

Private Property Get IGameState_PlayerJustMoved() As Long
IGameState_PlayerJustMoved = 2& - (m_t.nPlayerJustMoved And 1&)
End Property
